Skip to content

[manager] add cache location lookup metrics - #308

Open
Jaycby wants to merge 2 commits into
mainfrom
cache-hit-observability
Open

[manager] add cache location lookup metrics#308
Jaycby wants to merge 2 commits into
mainfrom
cache-hit-observability

Conversation

@Jaycby

@Jaycby Jaycby commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • add manager.location_lookup.requests_total to count valid location lookup requests
  • add manager.location_lookup.request_keys_total to count queried cache block keys
  • add manager.location_lookup.keys_total, split by result=hit|miss|filtered|error, to expose lookup outcomes
  • report the new counters through the KMonitor reporter without changing existing metric fields
  • keep per-instance metric collection aligned with the instance lifecycle and cover batch and masked-key lookup paths with tests

These counters provide the inputs needed to derive the cache-location hit rate in Grafana. The derived hit rate represents metadata location hits and does not imply that the cache payload was read successfully.

Validation

  • relevant manager and KMonitor reporter tests passed
  • image build pipeline passed
  • deployed the test image and confirmed that all three raw metrics are reported
  • verified the request rate, queried-key rate, result-key rate, and derived location hit-rate panels in Grafana

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@qoderai qoderai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

This PR adds clear, instance-scoped observability for cache-location lookups and wires the new counters through the KMonitor reporter. The test coverage for the prefix-match error classification, invalid-instance cardinality guard, instance lifecycle, and backend filtering paths is good.

Findings

  • Invalid requests may be counted. LocationLookupMetricsGuard is constructed before the query_type and backend-selector validation checks in both GetCacheLocation and GetCacheLocationsByBackend. Early returns from those checks will still emit manager.location_lookup.requests_total and manager.location_lookup.keys_total{error}, which conflicts with the stated goal of counting valid location lookups.
  • Guard default key count can misclassify errors. The guard is initialized with keys.size() and only updated to the real lookup count after validation. If a query fails before that update (e.g., prefix match with a mask or token-generated keys), the destructor records too many error keys.
  • Lifecycle lock scope is wide. The shared_lock on metrics_lifecycle_->mut_ is held for the entire request, including the metadata read and event publish. That guarantees the instance cannot be removed while metrics are written, but it also blocks RemoveInstance behind active backend reads. Consider scoping the lock to the metric guard lifetime.

Suggestions

  1. Move LocationLookupMetricsGuard construction (and the lifecycle lock) to after all request validation, and initialize it with the actual lookup_key_count.
  2. If the wide lock scope is intentional, add a brief comment explaining why it must cover the whole request rather than just the metric write.

No blocking issues—happy to re-review after the guard placement is tightened.


🤖 Generated by Qoder

RETURN_IF_EC_NOT_OK_WITH_TYPE_LOG(
WARN, EC_INSTANCE_NOT_EXIST, CacheLocationViewVecWrapper, "instance not found");
}
LocationLookupMetricsGuard location_metrics(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LocationLookupMetricsGuard is created before the query_type == QT_UNSPECIFIED check. If that check fails, the guard destructor still emits manager.location_lookup.requests_total and classifies all keys.size() keys as result=error. Since the PR description says requests_total counts valid lookups, consider moving the guard (and the lifecycle lock) after all request validation.


🤖 Generated by Qoder

if (instance_info == nullptr) {
RETURN_IF_EC_NOT_OK_WITH_TYPE_LOG(WARN, EC_INSTANCE_NOT_EXIST, BatchLocationsView, "instance not found");
}
LocationLookupMetricsGuard location_metrics(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same guard-placement issue here: the guard is constructed before validating query_type, block mask, location_spec_names, and backend_selectors. Any of those failures will emit requests_total and keys_total{error} for a request that never reached the lookup path. Constructing the guard after validation and initializing it with the real lookup_key_count would avoid counting invalid requests.


🤖 Generated by Qoder

// Keep a valid instance alive until the dynamic metric write completes.
// RemoveInstance holds the same lifecycle fence exclusively before it
// purges instance-tagged series.
std::shared_lock<std::shared_mutex> metrics_lifecycle_guard(metrics_lifecycle_->mut_);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The shared_lock is held for the whole request, including the metadata query, filtering, and event publish. This correctly prevents RemoveInstance from purging instance-tagged series while metrics are being written, but it also serializes instance removal behind active metadata reads. Consider scoping the lock to just the metric guard lifetime (validation → Complete) so removals are not blocked by backend latency. If the wider scope is intentional, a short comment would help future readers.


🤖 Generated by Qoder

const std::size_t lookup_key_count = query_type == QueryType::QT_PREFIX_MATCH
? CountUnmaskedKeys(query_keys, block_mask)
: query_keys.size();
location_metrics.SetRequestKeyCount(lookup_key_count);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If PerformCacheLocationQuery returns an error and the function returns before this line, the guard destructor records error keys using the initial keys.size() rather than the masked/generated lookup count. For prefix match with a mask or token-generated keys this over-counts error keys. Moving guard construction after validation and initializing it with the actual lookup_key_count would keep the error count consistent.


🤖 Generated by Qoder

@github-actions github-actions Bot added the ai reviewed AI has reviewed this PR label Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai reviewed AI has reviewed this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants